#include "chapter1_2.h"


class BaseIntArray
{
	protected:
		int *ia;
		int _size;
		void init(int sz, const int *pArray);
		void init(BaseIntArray &ia);
	private:
		int privateData;

	public:
		//base and sub class public member data
		int shareData;
		/* construction functions */		
		explicit BaseIntArray(int size = 100);
		BaseIntArray( const int *myarray, int array_size);
		BaseIntArray( const BaseIntArray &rhs);

		//BaseIntArray();
		//~BaseIntArray(){delete [] ia; }

		/* virtual deconstruction funcs */
		virtual ~BaseIntArray() {delete [] ia;}

		/* internal functions */
		int size() const{ return _size;}
		bool operator==(const BaseIntArray&) const;
		bool operator!=(const BaseIntArray&) const;
		BaseIntArray& operator=(const BaseIntArray&);

		virtual int & operator[ ] (int index) { return ia[index]; }
		//virtual void sort();
		//virtual int min() const;
		//virtual int max() const;
		//virtual int find() const;
};

//one coustruction function MUST, this call init() to init array.ia ans array.size
BaseIntArray::BaseIntArray( int array_size )
{
	init(array_size, 0);
}

BaseIntArray::BaseIntArray( const int *myarray, int array_size)
{
	init(array_size, myarray);
}

//protected func unsed by all instance of class or subclass
void BaseIntArray::init(int sz, const int *pArray)
{
	ia = NULL;
	ia = new int [sz] ;
	_size = sz;
	if(ia != NULL){ 
		if(NULL == pArray){
			for(int i = 0; i < sz; i++)
				ia[i] = 0;
		}
		else
		{
			for(int i = 0; i < sz; i++)
				ia[i] = *pArray++;
		}
	}

}

void BaseIntArray::init(BaseIntArray &ia)
{
	if(ia.ia != NULL){
		for(int i = 0; i < ia._size; i++)
			ia[i] = 0;
	}

}

class RCIntArray : public BaseIntArray
{
	public:
		//RCIntArray( );		//no need default no parameter construction func ?
		RCIntArray(int sz = 200);
		RCIntArray(int *inIa,int sz);
		RCIntArray(const BaseIntArray &rhs);
		virtual int& operator[ ] (int);
	private:
		void CheckRange(int index);

};
/* convert derived class constructor parameter to base-class constructor function */
//inline RCIntArray::RCIntArray( ) : BaseIntArray(  ) {}
inline RCIntArray::RCIntArray(int sz) : BaseIntArray( sz ) {}
inline RCIntArray::RCIntArray(int *inIa,int sz) : BaseIntArray(inIa, sz ) {}

inline void RCIntArray::CheckRange(int index)
{
	printf("Check array subscript, in = %d, max = %d\n", index, _size - 1);
	assert((index >=0) && (index < _size));
	
	//#error "assert err "
	//assert(privateData); #err to access private member of derived baseclass

}
inline int & RCIntArray::operator [ ](int index)
{
	CheckRange(index);
	return ia[index];

}

void sswap(BaseIntArray &ia, int index1,int index2)
{
	int tmp = ia[index1];
	ia[index1] = ia[index2];
	ia[index2] = tmp;
}


/******************************************* virtual base class ***************************************************/
class Base
{
public:
	int a;
	void set(int in) {a = in;};
	Base() {a = 10;};
};

class BaseLevelOne_A : virtual public Base
{
public:
	BaseLevelOne_A() { a = 1;};

};
class BaseLevelOne_B : virtual public Base
{
public:
	BaseLevelOne_B() { a = 2;};

};

class BaseLevelTwo : public BaseLevelOne_B, public BaseLevelOne_A
{
public:
	BaseLevelTwo():Base() {};

};

class BaseLevelOne_RA :  public Base
{
public:
	BaseLevelOne_RA() { a = 1;};

};
class BaseLevelOne_RB :  public Base
{
public:
	BaseLevelOne_RB() { a = 2;};

};

class BaseLevelTwo_R : public BaseLevelOne_RA, public BaseLevelOne_RB
{
public:
	//BaseLevelTwo_R(): {};

};


void testDerivedClass()
{
	int temparray[4] = {0, 1, 2, 3};

	BaseLevelTwo mutiBase;
	mutiBase.BaseLevelOne_A::a = 0x99;
	mutiBase.a = 0x88;
	mutiBase.set(0x89);

	BaseLevelTwo_R mutiBase_R;
	
	mutiBase_R.BaseLevelOne_RA::set(0x66);


	//define and init class object by constructor func 2
	BaseIntArray baseArray(temparray, 4);
	//init with construction func 1
	RCIntArray rcArray(temparray, 4);
	//init with default size=200 of baseclass
	RCIntArray noparaArray;

	//sswap(baseArray, 0, baseArray.size());
	//sswap(rcArray, 0, rcArray.size());
	{
		//int tmp = subArray._size;		//#err to access member of baseclass here, 
		int tmp = rcArray.size();		//#ok to access it by member function of derived subclass
		rcArray.shareData = tmp;		//#ok to access baseclass member,The best method
	}


}

